<?php


namespace app\xiangji\services;


use app\common\caches\SmsCache;
use app\common\caches\UserCache;
use app\common\facades\auth\Auth;
use app\common\helpers\Response;
use app\Request;
use app\common\models\User;
use app\xiangji\caches\ScoreRankCache;
use app\xiangji\exception\InvalidArgumentException;
use Carbon\Carbon;
use think\facade\Db;

class UserService
{
    private $userModel;
    private $wechatService;

    public function __construct(User $user, WechatService $wechatService)
    {
        $this->userModel        = $user;
        $this->wechatService    = $wechatService;
    }

    /**
     * @todo 微信小程序登录
     * @param Request $request  请求体
     * @return array    返回体：access_token：鉴权token，token_type:token类型，expires_in：token有效时间/秒
     * @throws \EasyWeChat\Kernel\Exceptions\DecryptException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function wxLogin(Request $request)
    {
        //  获取微信用户登录信息
        $code = $request->post('code');
        $iv = $request->post('iv');
        $encryptedData = $request->post('encryptedData');
        $wx_user = $this->wechatService->decryptUserInfo($code, $iv, $encryptedData);
        //  通过openId对比本地数据库，有就更新，无就新增
        $user = $this->userModel->where('openId', '=', $wx_user['openId'])->find();
        if (empty($user)){
            $user = $this->userModel->createRow($wx_user);
        }
        $token = Auth::guard('api')->login($user);
        // 是否有邀请人
        $inv_token = $request->post('token', '');
        // 有邀请人则绑定
        if ($inv_token){
            $invite_user = UserCache::getInviteLoverToken($inv_token);
            // 分享链接有效，要求人未绑定，本人未绑定，邀请人不是自己
            if ($invite_user && $invite_user->lover->lover_id == 0 && $user->lover->lover_id == 0 && $invite_user->id != $user->id){
                try {
                    (new UserLoverService())->bindLover($user, $invite_user);
                } catch (\Exception $e){
                    // 绑定失败只回滚，不报错
                }
            }
        }
        return [
            'access_token'  => 'bearer ' . $token,
            'token_type'    => 'bearer',
            'expires_in'    => config('jwt.ttl')
        ];
    }

    public function logout()
    {
        return Auth::guard('api')->logout();
    }

    /**
     * @todo 查询用户信息，包含恋人基本信息
     * @return mixed
     * @throws \GuzzleHttp\Exception\InvalidArgumentException
     */
    public function me()
    {
        $user = Auth::guard('api')->user()->hidden(['openId', 'unionId', 'create_time', 'update_time', 'delete_time']);
        $lover = $this->userModel->field(['id', 'gender', 'nickName', 'avatarUrl', 'login_time', 'login_ip'])->find($user->lover->lover_id);
        unset($user['lover']);  // 删除对象属性
        $user['lover'] = $lover;
        // 记录此次用户的登录信息
        $this->recordLoginInfo($user);
        return $user;
    }

    /**
     * 记录一下登录时间
     * @param User $user
     * @return bool
     */
    public function recordLoginInfo(User $user)
    {
        return $user->save([
            'login_time' => time(),
            'login_ip' => \request()->ip()
        ]);
    }

    /**
     * @todo 修改用户信息
     * @param Request $request
     * @return bool
     */
    public function modifyUserInfo(Request $request)
    {
        $update_info = $request->put(['nickName', 'gender', 'avatarUrl']);
        if (empty($update_info)) return true;
        $user = Auth::guard('api')->user();
        return $user->save($update_info);
    }

    /**
     * @todo 修改用户手机号
     * @param Request $request  用户请求
     * @return mixed
     * @throws \GuzzleHttp\Exception\InvalidArgumentException
     * @throws \think\Exception
     */
    public function modifyPhone(Request $request)
    {
        $mobile = $request->post('mobile');
        $verify_code = $request->post('verify_code');
        $cache_verify_code = SmsCache::getVerifyCode($mobile);

        if (!$cache_verify_code || $verify_code != $cache_verify_code){
            throw new InvalidArgumentException('验证码错误', Response::HTTP_BAD_REQUEST);
        }
        SmsCache::removeVerifyCode($mobile);
        $user = Auth::guard('api')->user();
        return $user->save(['mobile' => $mobile]);
    }

    public function userStatistics()
    {
        $user = Auth::guard('api')->user();
        $bind_lover_time = $user->lover->bind_time;
        $double_sign_times = $user->signs()->where('create_time', '>=', $bind_lover_time)->where('sign_status', '=', 2)->count('id');
        $anniversary_count = $user->anniversaries()->count('id');
        $bind_lover_days = Carbon::parse($bind_lover_time)->diffInDays(Carbon::today());
        return [
            'bind_lover_time'   => $bind_lover_time * 1000,
            'bind_lover_days'   => $bind_lover_days,
            'double_sign_count' => $double_sign_times,
            'anniversary_count' => $anniversary_count
        ];
    }

    public static function getUserLover(User $user)
    {
        return User::where('id', '=', $user->lover->lover_id)->find();
    }
}
